package com.my.swas.sso.module.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.my.swas.common.utils.BeanCopierUtil;
import com.my.swas.common.utils.CacheUtils;
import com.my.swas.sso.common.config.properties.SSOProperties;
import com.my.swas.sso.common.constans.CacheConst;
import com.my.swas.common.constans.CommConst;
import com.my.swas.sso.common.shiro.ShiroUtils;
import com.my.swas.sso.module.admin.entity.Role;
import com.my.swas.sso.module.admin.entity.User;
import com.my.swas.sso.enums.OperationType;
import com.my.swas.sso.module.admin.dto.UserDto;
import com.my.swas.sso.module.admin.mapper.RoleMapper;
import com.my.swas.sso.module.admin.mapper.UserMapper;
import com.my.swas.sso.module.admin.service.RoleService;
import com.my.swas.sso.module.admin.service.UserService;
import com.my.swas.sso.module.admin.vo.UserVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description:
 * @author: :MaYong
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private RoleMapper roleMapper;
    @Resource
    private SSOProperties ssoProperties;
    @Resource
    private RoleService roleService;
    @Resource
    CacheUtils cacheUtils;

    @Override
    public IPage<UserVo> pageList(UserDto userDto) {
        User user = new User();
        BeanCopierUtil.convert(userDto, user);
        Page pageInfo = (Page) super.page(userDto.getPage(), new QueryWrapper<>(user));
        List<User> userList = pageInfo.getRecords();
        if (CollectionUtils.isEmpty(userList)) {
            return pageInfo;
        }
        pageInfo.setRecords(setRoleToUserVoList(userList));
        return pageInfo;
    }

    @Override
    public Integer updateVerifyCount(User record) {
        if (null == record) return CommConst.ZERO;
        if (null == record.getVerifyCount()) record.setVerifyCount(CommConst.ZERO);
        if (Integer.valueOf(ssoProperties.getVerifyCount()).compareTo(record.getVerifyCount()) == 0) {
            record.setVerifyCount(CommConst.FIVE);
            record.setEnable(CommConst.TWO);
        }
        baseMapper.updateById(record);
        return record.getVerifyCount();
    }

    @Override
    public List<UserVo> getUserVoList(UserDto userDto) {
        User user = new User();
        BeanCopierUtil.convert(userDto, user);
        List<User> userList = baseMapper.selectList(new QueryWrapper<>(user));
        return setRoleToUserVoList(userList);
    }

    @Override
    public UserVo getUserVo(Long userId) {
        User dbUser = baseMapper.selectById(userId);
        if (null == dbUser) {
            return null;
        }
        return setRoleToUserVoList(Lists.newArrayList(dbUser)).get(0);
    }

    @Override
    public void grantRoles(Long userId, String roleIds) {
        User user = new User();
        user.setId(userId);
        user.setRoleIds(roleIds);
        baseMapper.updateById(user);
        if (StringUtils.isNotBlank(roleIds)) {
            roleService.buildRoleGrant(userId);
        } else {
            cacheUtils.remove(CacheConst.EH_USER_ROLES_FOR_SELECT + userId);
        }
        ShiroUtils.refresh();
    }

    @Override
    public void verifyCount(Long userId, Integer verifyCount, OperationType operationType) {
        User userVerifyCount = new User();
        userVerifyCount.setId(userId);
        if (OperationType.PLUS.equals(operationType)) {
            userVerifyCount.setVerifyCount(verifyCount + CommConst.ONE);
        } else if (OperationType.SUBTRACT.equals(operationType)) {
            userVerifyCount.setVerifyCount(verifyCount - CommConst.ONE);
        } else if (OperationType.ZERO.equals(operationType) || verifyCount == null) {
            userVerifyCount.setVerifyCount(0);
        }
        updateVerifyCount(userVerifyCount);
    }


    private List<UserVo> setRoleToUserVoList(List<User> userList) {
        Set<Long> roleIds = Sets.newConcurrentHashSet();
        userList.forEach(u -> Splitter.on(",").splitToList(u.getRoleIds()).forEach(s -> roleIds.add(Long.valueOf(s))));

        List<Role> roleList = roleMapper.selectBatchIds(roleIds);
        Map<Long, List<Role>> roleMap = roleList.stream()
                .collect(Collectors.groupingBy(Role::getId));
        List<UserVo> userVos = Lists.newArrayList();
        userList.forEach(u -> {
            UserVo userVo = new UserVo();
            BeanUtil.copyProperties(u, userVo);
            List<Role> all = Lists.newArrayList();
            Splitter.on(",").splitToList(u.getRoleIds())
                    .forEach(s -> all.addAll(roleMap.get(Long.valueOf(s))));
            userVo.setRoleList(all);
            userVos.add(userVo);
        });
        return userVos;
    }


    public List<UserVo> transferToVoForList(List<User> userList) {
        List<UserVo> userVos = Lists.newArrayList();
        userList.forEach(user -> userVos.add(transferToVo(user)));
        return userVos;
    }

    public UserVo transferToVo(User user) {
        UserVo userVos = new UserVo();
        BeanCopierUtil.convert(user, userVos);
        return userVos;
    }
}
